%
%  Usage : m = Manager(Parameters())
%
classdef Manager < handle
    
    properties (GetAccess = public, SetAccess = private)
        Parameters
        % vector of all neurons
        Neurons
        % vector of all synapses
        Synapses
    end
    
    methods
        
        function Run(obj)
            for i=1:obj.Parameters.Iterations
                obj.UpdateInput();
                [activatedNeurons] = obj.UpdateNeurons();
                obj.UpdateSynapses();
                obj.Draw(activatedNeurons);
                pause(3);
                
            end
        end
        
        function UpdateInput(obj)
           obj.Neurons(1).ReceiveCharge(10);
           obj.Neurons(2).ReceiveCharge(10);
        end
        
        
        function [ret] = UpdateNeurons(obj)
            result = [];
            for i=1:length(obj.Neurons)
                [neuronResult] = obj.Neurons(i).Update();
                if neuronResult == 1
                    result = [result, obj.Neurons(i)];
                end
            end            
            ret = result;
        end
        
        function UpdateSynapses(obj)
            for i=1:length(obj.Synapses)
                obj.Synapses(i).Update();
            end
        end
        
        function Draw(obj,activatedNeurons)
            radius = 3;
            distance = 10;
            neuronsPosition = [];
                        
            clf('reset')
            hold on
            
            n = floor(sqrt(obj.Parameters.NumOfNeurons));
            
            for i=1:n
                for j=1:n
                    [x,y] = cylinder(radius,200);
                    plot(x(1,:)+i*distance,y(1,:)+j*distance)                    
                    neuronsPosition = [neuronsPosition; [i*distance,j*distance]];                    
                    text(i*distance,j*distance,int2str(length(obj.Neurons(n*(i-1)+j).Synapses)));
                    
                    if len(activatedNeurons > 0)
                        if( find(activatedNeurons == obj.Neurons(n*(i-1)+j)))
                            plot(x(1,:)+i*distance,y(1,:)+j*distance,'Color','r');
                        end
                    end
                    
                    
                end
            end  
            
            for i=1:obj.Parameters.NumOfNeurons-(n*n)
                [x,y] = cylinder(radius,100);
                plot(x(1,:)+i*distance,y(1,:)+(n+1)* distance);
                neuronsPosition = [neuronsPosition ; [i*distance,(n+1)* distance]];
                text(i*distance,(n+1)* distance,int2str(length(obj.Neurons( length(neuronsPosition) ).Synapses)));
            end
            
            
            colors = lines(length(obj.Neurons));            
            for i=1:length(obj.Neurons)               
                for j=1:length(obj.Neurons(i).Synapses)
                    startIndex = i;
                    endIndex = find(obj.Neurons == obj.Neurons(i).Synapses(j).PostSynapticNeuron);
                    line( [neuronsPosition(startIndex,1),neuronsPosition(endIndex,1)+ rand()*4-2] , [neuronsPosition(startIndex,2),neuronsPosition(endIndex,2)+ rand()*4-2], 'Color',colors(i,:));
                end                
            end

            
            
                                   
            axis equal
            hold off
        end
        
        
        function ret = Manager(parameters)
            ret.Parameters = parameters;
            
            % initialize neurons            
            ret.Neurons = [];
            
            for i=1:ret.Parameters.NumOfNeurons
                ret.Neurons = [ret.Neurons Neuron(ret.Parameters, 1)];
            end
            
            % make random neuron connections
            neuronConnections = ceil(rand(ret.Parameters.NumOfSynapses, 2) * ret.Parameters.NumOfNeurons);
            
            for i=1:ret.Parameters.NumOfSynapses
                preSynapticNeuron = ret.Neurons(neuronConnections(i, 1));
                postSynapticNeuron = ret.Neurons(neuronConnections(i, 2));
                
                if preSynapticNeuron ~= postSynapticNeuron
                    newSynapse = Synapse(ret.Parameters, postSynapticNeuron);                                
                    preSynapticNeuron.AddSynapse(newSynapse);                
                    ret.Synapses = [ret.Synapses newSynapse];
                end
            end
            
        end
        
    end
    
end

